package com.stqf.scala.grammar

import java.util.Date

/**
 * Created By stqf
 * Date: 19-5-14
 * Description: Scala函数
 */
object Func {
  def main(args: Array[String]): Unit = {
    /*函数传名调用*/
    delayed(times())
    /*指定函数参数名*/
    printInt(num2 = 30, num1 = 2)
    /*可变参数*/
    printStr("Go", "Java", "Scala", "Python", "R", "C++")
    /*递归函数*/
    for (value <- 1 to 15) {
      println(value + "的阶乘为:" + factorial(value))
    }
    /*默认参数值*/
    println(addInt())
    /*高阶函数*/
    println(apply(layout, 20))
    /*函数嵌套*/
    println(factorial(0))
    println(factorial(1))
    println(factorial(2))
    println(factorial(3))
    /*匿名函数*/
    println(div(10, 5))
    /*偏应用函数*/
    val logWithDateBound = log(new Date(), _: String)
    logWithDateBound("message_01")
    logWithDateBound("message_02")
    logWithDateBound("message_03")
    /*函数柯里化*/
    val res = subtract(50) _
    println(res(20))
  }

  /** ---------->函数柯里化【start】<---------- */
  def subtract(num1: Int)(num2: Int): Int = {
    num1 - num2
  }

  /** ---------->函数柯里化【finish】<---------- */


  /** ---------->偏应用函数【start】<---------- */
  def log(date: Date, message: String) = {
    println(date + "----->" + message)
  }

  /** ---------->偏应用函数【finish】<---------- */


  /** ---------->匿名函数【start】<---------- */
  val div = (x: Int, y: Int) => x / y

  /** ---------->匿名函数【finish】<---------- */

  /** ---------->函数嵌套【start】<---------- */
  def factorial(num: Int): Int = {
    def fact(num: Int, value: Int): Int = {
      if (num <= 1) return value
      fact(num - 1, num * value)
    }

    fact(num, 1)
  }

  /** ---------->函数嵌套【finish】<---------- */

  /** ---------->高阶函数【start】<---------- */
  def apply(f: Int => String, v: Int) = f(v)

  def layout[A](x: A) = "[" + x.toString + "]"

  /** ---------->高阶函数【finish】<---------- */


  /** ---------->默认参数值【start】<---------- */
  def addInt(num1: Int = 3, num2: Int = 5): Int = {
    return num1 + num2
  }

  /** ---------->默认参数值【finish】<---------- */

  /** ---------->递归函数【start】<---------- */
  def factorial(num: BigInt): BigInt = {
    if (num <= 1) {
      return 1
    } else {
      return num * factorial(num - 1)
    }
  }

  /** ---------->递归函数【finish】<---------- */

  /** ---------->可变参数【start】<---------- */
  private def printStr(args: String*) = {
    var index = 0
    for (elem <- args) {
      println("Arg value[" + index + "]" + elem)
      index += 1
    }
  }

  /** ---------->可变参数【finish】<---------- */

  /** ---------->指定函数参数名【start】<---------- */
  private def printInt(num1: Int, num2: Int) = {
    println("value of num1:" + num1)
    println("value of num2:" + num2)
  }

  /** ---------->指定函数参数名【finish】<---------- */


  /** ---------->函数传名调用【start】<---------- */
  private def times() = {
    println("获取时间，单位纳秒")
    System.nanoTime()
  }

  private def delayed(t: => Long) = {
    println("method delayed")
    println("params:" + t)
  }

  /** ---------->函数传名调用【finish】<---------- */
}
